package com.derbysoft.dswitch.adapter.ihg.dswitch3.service.impl;

import com.derbysoft.dswitch.adapter.ihg.common.log.LogBody;
import com.derbysoft.dswitch.adapter.ihg.common.log.PerformanceLogger;
import com.derbysoft.dswitch.adapter.ihg.common.utils.EnvironmentUtils;
import com.derbysoft.dswitch.adapter.ihg.dswitch3.HotelProviderService;
import com.derbysoft.dswitch.adapter.ihg.dswitch3.translate.Translator;
import com.derbysoft.dswitch.adapter.ihg.exception.InvokeProviderSideException;
import com.derbysoft.dswitch.adapter.ihg.dto.OTAHotelAvailRQ;
import com.derbysoft.dswitch.adapter.ihg.dto.OTAHotelAvailRS;
import com.derbysoft.dswitch.adapter.ihg.webservice.handler.WebServiceHandler;
import com.derbysoft.dswitch.adapter.ihg.webservice.impl.AccountProvider;
import com.derbysoft.dswitch.adapter.ihg.webservice.impl.RequestPair;
import com.derbysoft.dswitch.adapter.ihg.webservice.impl.ResponsePair;
import com.derbysoft.dswitch.dto.common.KeyValue;
import com.derbysoft.dswitch.remote.hotel.dto.ErrorDTO;
import com.derbysoft.dswitch.remote.hotel.dto.HotelAvailRequest;
import com.derbysoft.dswitch.remote.hotel.dto.HotelAvailResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.util.List;

/**
 * Created by: jason
 * Date: 2012-5-8
 */
@Service("hotelMultiAvailabilityService")
public class HotelMultiAvailabilityServiceImpl extends BaseHotelService
        implements HotelProviderService<HotelAvailRequest, HotelAvailResponse> {

    @Autowired
    @Qualifier("hotelMultiAvailRQTranslator")
    private Translator<HotelAvailRequest, List<RequestPair<OTAHotelAvailRQ>>, Void> hotelAvailRQTranslator;

    @Autowired
    @Qualifier("hotelMultiAvailRSTranslator")
    private Translator<List<ResponsePair<OTAHotelAvailRQ, OTAHotelAvailRS>>, HotelAvailResponse, HotelAvailRequest> hotelAvailRSTranslator;

    @Autowired
    @Qualifier("availWebServiceHandler")
    private WebServiceHandler<OTAHotelAvailRQ, OTAHotelAvailRS> hotelAvailWebService;

    @Override
    public HotelAvailResponse invoke(HotelAvailRequest request ) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        try {
            List<RequestPair<OTAHotelAvailRQ>> otaHotelAvailRQs = hotelAvailRQTranslator.translate(request, null);

            List<ResponsePair<OTAHotelAvailRQ, OTAHotelAvailRS>> hotelAvailRSes = hotelAvailWebService.batchInvoke(otaHotelAvailRQs,
                    AccountProvider.of(EnvironmentUtils.getGlobalIhgAvailabilityUrl(), loadAuthorization(request.getHeader().getSource())));
            stopWatch.stop();
            long webserviceTime = stopWatch.getTotalTimeMillis();

            HotelAvailResponse hotelAvailResponse = hotelAvailRSTranslator.translate(hotelAvailRSes, request);

            hotelAvailResponse.getElapsedTimes().add(new KeyValue(ElapsedTimeType.AVAIL.name(), String.valueOf(webserviceTime)));

            return hotelAvailResponse;
        } catch (Exception ex) {
            if (stopWatch.isRunning()) {
                stopWatch.stop();
            }
            long webserviceTime = stopWatch.getTotalTimeMillis();
            HotelAvailResponse errorResponse = createErrorResponse(request, ex);
            errorResponse.getElapsedTimes().add(new KeyValue(ElapsedTimeType.AVAIL.name(), String.valueOf(webserviceTime)));
            PerformanceLogger.append(LogBody.ERROR_CODE, errorResponse.getError().getCode());
            return errorResponse;
        }
    }

    private HotelAvailResponse createErrorResponse(HotelAvailRequest request, Exception ex) {
        HotelAvailResponse response = new HotelAvailResponse();
        response.setTaskId(request.getHeader().getTaskId());
        ErrorDTO errorDTO = new ErrorDTO();
        errorDTO.setCode(SYSTEM);
        errorDTO.setSource(ex instanceof InvokeProviderSideException ? provider : adapter);
        errorDTO.setMessage(ex.getMessage());
        response.setError(errorDTO);
        return response;
    }
}
